package com.one.group.admin.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.one.group.admin.mapper.AdminMapper;
import com.one.group.admin.mapper.OwnerMapper;
import com.one.group.admin.mapper.ParkingSpaceMapper;
import com.one.group.admin.mapper.VehicleSpaceMapper;
import com.one.group.enums.ErrorCode;
import com.one.group.exception.BusinessException;
import com.one.group.model.dto.ParkingSpaceAddDto;
import com.one.group.model.dto.ParkingSpaceBindDto;
import com.one.group.model.dto.ParkingSpaceChargeBatchBindDto;
import com.one.group.model.dto.ParkingSpaceChargeBindDto;
import com.one.group.model.dto.ParkingSpaceChargeUnbindDto;
import com.one.group.model.dto.ParkingSpaceQueryDto;
import com.one.group.model.dto.ParkingSpaceUnbindDto;
import com.one.group.model.entity.Admin;
import com.one.group.model.entity.ParkingSpace;
import com.one.group.model.entity.ParkingSpaceCharge;
import com.one.group.model.entity.SpChargeStandards;
import com.one.group.model.entity.VehicleSpace;
import static com.one.group.model.entity.table.ParkingSpaceChargeTableDef.PARKING_SPACE_CHARGE;
import com.one.group.model.vo.ParkingSpaceDetailVo;
import com.one.group.model.vo.ParkingSpaceListVo;
import com.one.group.model.vo.ParkingSpaceSearchVo;
import com.one.group.service.ParkingSpaceService;
import com.one.group.service.SpChargeStandardsService;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class ParkingSpaceServiceImpl extends ServiceImpl<ParkingSpaceMapper, ParkingSpace> implements ParkingSpaceService {

    @Autowired
    private ParkingSpaceMapper parkingSpaceMapper;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private VehicleSpaceMapper vehicleSpaceMapper;
    @Autowired
    private SpChargeStandardsService spChargeStandardsService;
    @Autowired
    private OwnerMapper ownerMapper;


    @Override
    public List<ParkingSpaceListVo> findParkingSpaceByQueryDto(ParkingSpaceQueryDto parkingSpaceQueryDto) {

        //获取当前租户id
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        parkingSpaceQueryDto.setTenantId(tenantId);
        return parkingSpaceMapper.findParkingSpaceByQueryDto(parkingSpaceQueryDto);
    }

    @Override
    public boolean addParkingSpace(ParkingSpaceAddDto parkingSpaceAddDto) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));

        // 检查车位编号是否已存在
        ParkingSpace existingSpace = parkingSpaceMapper.selectOneBySpaceNoAndCellId(
                parkingSpaceAddDto.getSpaceNo(),
                parkingSpaceAddDto.getCellId(),
                tenantId
        );
        if (existingSpace != null) {
            throw new BusinessException(ErrorCode.Data_CODE_EXITS, "该小区下已存在相同编号的车位");
        }

        // 创建车位实体
        ParkingSpace parkingSpace = new ParkingSpace();
        parkingSpace.setCellId(parkingSpaceAddDto.getCellId());
        parkingSpace.setSpaceNo(parkingSpaceAddDto.getSpaceNo());
        parkingSpace.setType(parkingSpaceAddDto.getType());
        parkingSpace.setStatus(parkingSpaceAddDto.getStatus());
        parkingSpace.setArea(parkingSpaceAddDto.getArea());
        parkingSpace.setLocation(parkingSpaceAddDto.getLocation());
        parkingSpace.setRemark(parkingSpaceAddDto.getRemark());
        parkingSpace.setCreatedTime(new Date());
        parkingSpace.setUpdatedTime(new Date());

        // 设置租户ID
        parkingSpace.setTenantId(tenantId);

        // 保存车位
        return save(parkingSpace);
    }

    @Override
    public boolean deleteParkingSpace(Long id) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));

        // 检查车位是否存在
        ParkingSpace parkingSpace = getById(id);
        if (parkingSpace == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), "车位不存在");
        }

        // 检查租户权限
        if (!parkingSpace.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR.getCode(), "无权限删除该车位");
        }

        // 检查车位是否被占用
        if (parkingSpace.getStatus() != null && parkingSpace.getStatus() == 5) {
            throw new BusinessException(ErrorCode.DELETE_ERROR.getCode(), "车位正在被占用，无法删除");
        }

        // 检查是否有车辆绑定
        boolean hasVehicleBinding = parkingSpaceMapper.hasVehicleBinding(id);
        if (hasVehicleBinding) {
            throw new BusinessException(ErrorCode.DELETE_ERROR.getCode(), "车位已绑定车辆，请先解除绑定再删除");
        }

        // 检查是否有收费标准绑定
        boolean hasChargeBinding = parkingSpaceMapper.hasChargeBinding(id);
        if (hasChargeBinding) {
            throw new BusinessException(ErrorCode.DELETE_ERROR.getCode(), "车位已绑定收费标准，请先解除绑定再删除");
        }

        // 删除车位
        return removeById(id);
    }

    @Override
    public boolean batchDeleteParkingSpaces(List<Long> ids) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));

        // 检查所有车位是否存在且属于当前租户
        for (Long id : ids) {
            ParkingSpace parkingSpace = getById(id);
            if (parkingSpace == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), "车位ID " + id + " 不存在");
            }

            // 检查租户权限
            if (!parkingSpace.getTenantId().equals(tenantId)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR.getCode(), "无权限删除车位ID " + id);
            }

            // 检查车位是否被占用
            if (parkingSpace.getStatus() != null && parkingSpace.getStatus() == 5) {
                throw new BusinessException(ErrorCode.DELETE_ERROR.getCode(), "车位 " + parkingSpace.getSpaceNo() + " 正在被占用，无法删除");
            }

            // 检查是否有车辆绑定
            boolean hasVehicleBinding = parkingSpaceMapper.hasVehicleBinding(id);
            if (hasVehicleBinding) {
                throw new BusinessException(ErrorCode.DELETE_ERROR.getCode(), "车位 " + parkingSpace.getSpaceNo() + " 已绑定车辆，请先解除绑定再删除");
            }

            // 检查是否有收费标准绑定
            boolean hasChargeBinding = parkingSpaceMapper.hasChargeBinding(id);
            if (hasChargeBinding) {
                throw new BusinessException(ErrorCode.DELETE_ERROR.getCode(), "车位 " + parkingSpace.getSpaceNo() + " 已绑定收费标准，请先解除绑定再删除");
            }
        }

        // 批量删除车位
        return removeByIds(ids);
    }

    @Override
    public boolean bindVehicle(ParkingSpaceBindDto bindDto) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        
        // 检查车位是否存在
        ParkingSpace parkingSpace = getById(bindDto.getParkingSpaceId());
        if (parkingSpace == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), "车位不存在");
        }
        
        // 检查租户权限
        if (!parkingSpace.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR.getCode(), "无权限操作该车位");
        }

        // 检查是否已存在绑定关系
        QueryWrapper queryWrapper = QueryWrapper.create().from(VehicleSpace.class);
        queryWrapper.eq(VehicleSpace::getParkingSpaceId, bindDto.getParkingSpaceId())
                   .eq(VehicleSpace::getVehicleId, bindDto.getVehicleId())
                   .eq(VehicleSpace::getTenantId, tenantId);
        VehicleSpace existingBinding = vehicleSpaceMapper.selectOneByQuery(queryWrapper);
        
        if (existingBinding != null) {
            // 如果存在绑定关系且状态为有效，则提示已绑定
            if (existingBinding.getStatus() == 1) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR.getCode(), "该车辆与车位已存在有效绑定关系");
            }
            
            // 如果存在绑定关系但状态不为有效，则更新为有效状态
            existingBinding.setBindType(bindDto.getBindType());
            existingBinding.setAuthorizeStart(bindDto.getAuthorizeStart());
            existingBinding.setAuthorizeEnd(bindDto.getAuthorizeEnd());
            existingBinding.setStatus(1); // 有效
            existingBinding.setUpdatedTime(new Date());
            
            //经办人即当前登录用户
            Long id = Convert.toLong(StpUtil.getLoginId());
            Admin admin = adminMapper.selectOneById(id);
            existingBinding.setCreatedBy(admin.getName());
            
            return vehicleSpaceMapper.update(existingBinding) > 0;
        }

        //经办人即当前登录用户
        Long id = Convert.toLong(StpUtil.getLoginId());
        Admin admin = adminMapper.selectOneById(id);

        // 创建新的绑定记录
        VehicleSpace vehicleSpace = new VehicleSpace();
        vehicleSpace.setCellId(parkingSpace.getCellId());
        vehicleSpace.setVehicleId(bindDto.getVehicleId());
        vehicleSpace.setParkingSpaceId(bindDto.getParkingSpaceId());
        vehicleSpace.setBindType(bindDto.getBindType());
        vehicleSpace.setAuthorizeStart(bindDto.getAuthorizeStart());
        vehicleSpace.setAuthorizeEnd(bindDto.getAuthorizeEnd());
        vehicleSpace.setStatus(1); // 有效
        vehicleSpace.setCreatedTime(new Date());
        vehicleSpace.setUpdatedTime(new Date());
        vehicleSpace.setCreatedBy(admin.getName());
        vehicleSpace.setTenantId(tenantId);
        
        return vehicleSpaceMapper.insert(vehicleSpace) > 0;
    }

    @Override
    public boolean unbindVehicle(ParkingSpaceUnbindDto unbindDto) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        
        // 检查车位是否存在
        ParkingSpace parkingSpace = getById(unbindDto.getParkingSpaceId());
        if (parkingSpace == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "车位不存在");
        }
        
        // 检查租户权限
        if (!parkingSpace.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作该车位");
        }

        // 检查绑定关系是否存在
        QueryWrapper queryWrapper = QueryWrapper.create().from(VehicleSpace.class);
        queryWrapper.eq(VehicleSpace::getParkingSpaceId, unbindDto.getParkingSpaceId())
                   .eq(VehicleSpace::getVehicleId, unbindDto.getVehicleId())
                   .eq(VehicleSpace::getTenantId, tenantId);
        VehicleSpace existingBinding = vehicleSpaceMapper.selectOneByQuery(queryWrapper);
        if (existingBinding == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "车辆与车位绑定关系不存在");
        }

        // 检查绑定状态是否为有效
        if (existingBinding.getStatus() != 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "该绑定关系已失效，无需解绑");
        }

        // 执行解绑操作（将状态更新为已解除）
        return parkingSpaceMapper.updateVehicleSpaceStatus(
            existingBinding.getId(), 3, tenantId) > 0; // 3表示已解除
    }

    @Override
    public ParkingSpaceDetailVo getParkingSpaceDetail(Long id) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        
        // 检查车位是否存在
        ParkingSpace parkingSpace = getById(id);
        if (parkingSpace == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "车位不存在");
        }
        
        // 检查租户权限
        if (!parkingSpace.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限查看该车位信息");
        }
        
        return parkingSpaceMapper.getParkingSpaceDetail(id, tenantId);
    }

    @Override
    public boolean bindChargeStandard(ParkingSpaceChargeBindDto bindDto) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        
        // 检查车位是否存在
        ParkingSpace parkingSpace = getById(bindDto.getParkingSpaceId());
        if (parkingSpace == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "车位不存在");
        }
        
        // 检查租户权限
        if (!parkingSpace.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作该车位");
        }
        
        // 检查收费标准是否存在
        SpChargeStandards chargeStandard = spChargeStandardsService.getById(bindDto.getChargeStandardId());
        if (chargeStandard == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "收费标准不存在");
        }
        
        // 检查收费标准租户权限
        if (!chargeStandard.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作该收费标准");
        }
        
        // 检查是否已绑定 - 使用QueryWrapper
        QueryWrapper bindingQuery = QueryWrapper.create()
                .from(PARKING_SPACE_CHARGE)
                .where(PARKING_SPACE_CHARGE.PARKING_SPACE_ID.eq(bindDto.getParkingSpaceId()))
                .and(PARKING_SPACE_CHARGE.CHARGE_STANDARD_ID.eq(bindDto.getChargeStandardId()))
                .and(PARKING_SPACE_CHARGE.TENANT_ID.eq(tenantId));
        
        boolean hasBinding = parkingSpaceMapper.selectCountByQuery(bindingQuery) > 0;
        if (hasBinding) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "该车位已绑定此收费标准");
        }
        
        // 创建绑定记录
        ParkingSpaceCharge parkingSpaceCharge = new ParkingSpaceCharge();
        parkingSpaceCharge.setParkingSpaceId(bindDto.getParkingSpaceId());
        parkingSpaceCharge.setChargeStandardId(bindDto.getChargeStandardId());
        parkingSpaceCharge.setAmountOverride(bindDto.getAmountOverride() != null ? 
                bindDto.getAmountOverride() : chargeStandard.getPrice());
        parkingSpaceCharge.setIsCurrent(bindDto.getIsCurrent());
        parkingSpaceCharge.setCreatedTime(new Date());
        parkingSpaceCharge.setUpdatedTime(new Date());
        parkingSpaceCharge.setTenantId(tenantId);
        
        return parkingSpaceMapper.insertParkingSpaceCharge(parkingSpaceCharge) > 0;
    }

    @Override
    public boolean batchBindChargeStandard(ParkingSpaceChargeBatchBindDto batchBindDto) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        
        // 检查收费标准是否存在
        SpChargeStandards chargeStandard = spChargeStandardsService.getById(batchBindDto.getChargeStandardId());
        if (chargeStandard == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "收费标准不存在");
        }
        
        // 检查收费标准租户权限
        if (!chargeStandard.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作该收费标准");
        }
        
        // 检查所有车位
        for (Long parkingSpaceId : batchBindDto.getParkingSpaceIds()) {
            ParkingSpace parkingSpace = getById(parkingSpaceId);
            if (parkingSpace == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "车位ID " + parkingSpaceId + " 不存在");
            }
            
            // 检查租户权限
            if (!parkingSpace.getTenantId().equals(tenantId)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作车位ID " + parkingSpaceId);
            }
            
            // 检查是否已绑定 - 使用QueryWrapper
            QueryWrapper bindingQuery = QueryWrapper.create()
                    .from(PARKING_SPACE_CHARGE)
                    .where(PARKING_SPACE_CHARGE.PARKING_SPACE_ID.eq(parkingSpaceId))
                    .and(PARKING_SPACE_CHARGE.CHARGE_STANDARD_ID.eq(batchBindDto.getChargeStandardId()))
                    .and(PARKING_SPACE_CHARGE.TENANT_ID.eq(tenantId));
            
            boolean hasBinding = parkingSpaceMapper.selectCountByQuery(bindingQuery) > 0;
            if (hasBinding) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "车位ID " + parkingSpaceId + " 已绑定此收费标准");
            }
        }
        
        // 批量创建绑定记录
        for (Long parkingSpaceId : batchBindDto.getParkingSpaceIds()) {
            ParkingSpaceCharge parkingSpaceCharge = new ParkingSpaceCharge();
            parkingSpaceCharge.setParkingSpaceId(parkingSpaceId);
            parkingSpaceCharge.setChargeStandardId(batchBindDto.getChargeStandardId());
            parkingSpaceCharge.setAmountOverride(batchBindDto.getAmountOverride() != null ? 
                    batchBindDto.getAmountOverride() : chargeStandard.getPrice());
            parkingSpaceCharge.setIsCurrent(batchBindDto.getIsCurrent());
            parkingSpaceCharge.setCreatedTime(new Date());
            parkingSpaceCharge.setUpdatedTime(new Date());
            parkingSpaceCharge.setTenantId(tenantId);
            
            int result = parkingSpaceMapper.insertParkingSpaceCharge(parkingSpaceCharge);
            if (result <= 0) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "绑定车位ID " + parkingSpaceId + " 失败");
            }
        }
        
        return true;
    }

    @Override
    public boolean unbindChargeStandard(ParkingSpaceChargeUnbindDto unbindDto) {
        try {
            // 获取租户ID
            Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));

            // 检查车位是否存在
            ParkingSpace parkingSpace = getById(unbindDto.getParkingSpaceId());
            if (parkingSpace == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "车位不存在");
            }

            // 检查租户权限
            if (!parkingSpace.getTenantId().equals(tenantId)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作该车位");
            }

            // 删除绑定记录
            int result = parkingSpaceMapper.deleteParkingSpaceCharge(
                    unbindDto.getParkingSpaceId(), unbindDto.getChargeStandardId(), tenantId);

            if (result <= 0) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到绑定记录");
            }
        } catch (BusinessException e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "解绑失败:"+e.getMessage());
        }
        
        return true;
    }

    @Override
    public List<ParkingSpaceSearchVo> searchParkingSpacesBySpaceNo(String spaceNo, Long cellId) {
        // 获取当前租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        return parkingSpaceMapper.searchParkingSpacesBySpaceNo(spaceNo, cellId, tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindOwner(Long parkingSpaceId, Long ownerId) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));

        int result;
        try {
            if(ownerMapper.getStatusById(ownerId, tenantId)!= 1){
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "只有已迁入的业主才能绑定车位！");
            }
            int type = parkingSpaceMapper.getTypeById(parkingSpaceId, tenantId);
            if (type != 1) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "只有类型为产权车位的车位才能绑定住户！");
            }
            int status = parkingSpaceMapper.getStatusById(parkingSpaceId, tenantId);
            if (status != 1 && status != 4) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "只有状态为空置和出售的车位才能绑定住户！");
            }
            int bindResult = parkingSpaceMapper.addOwnerIdById(parkingSpaceId, ownerId, tenantId);
            if (bindResult <= 0) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "绑定住户失败");
            }
            // 更新车位状态为2：自用
            result = parkingSpaceMapper.updateStatus(parkingSpaceId, 2, tenantId);
        } catch (BusinessException e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "绑定住户失败:"+e.getMessage());
        }
        return result > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unbindOwner(Long parkingSpaceId) {
        // 获取租户ID
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        try {
            if(parkingSpaceMapper.getOwnerIdById(parkingSpaceId, tenantId) == null){
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "此车位没有绑定住户！");
            }
            int type = parkingSpaceMapper.getTypeById(parkingSpaceId, tenantId);
            if (type != 1) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "只有类型为产权车位的车位才能接触绑定住户！");
            }
            int status = parkingSpaceMapper.getStatusById(parkingSpaceId, tenantId);
            if (status != 2) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "只有状态为自用的车位才能接触绑定住户！");
            }
            // 解绑
            int unBindResult = parkingSpaceMapper.addOwnerIdById(parkingSpaceId, null, tenantId);
            if (unBindResult <= 0) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "解绑住户失败");
            }
        } catch (BusinessException e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "解绑住户失败:"+e.getMessage());
        }
        // 更新车位状态为4：出售
        return parkingSpaceMapper.updateStatus(parkingSpaceId, 4, tenantId) > 0;
    }


}